﻿#region Copyright (c) 2000-2013 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{                                                                   }
{                                                                   }
{       Copyright (c) 2000-2013 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2013 Developer Express Inc.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
#if !REALTORWORLDDEMO
using System.Windows;
using System.Deployment.Application;
using DevExpress.Internal.DXWindow;
#endif
#if REALTORWORLDDEMO
namespace DevExpress.RealtorWorld.Xpf.Helpers {
#else
namespace UColor.Core.Helpers {
#endif
	public sealed class ReusableStream : IDisposable {
		Stream data;
		AutoResetEvent mutex;
		public ReusableStream() {
			this.mutex = new AutoResetEvent(true);
		}
		public Stream Data {
			get { return data; }
			set {
				data = value;
				if(data != null && !data.CanSeek)
					data = StreamHelper.CopyToMemoryStream(data);
			}
		}
		public void Reset() {
			this.mutex.WaitOne();
			if(this.data != null)
				this.data.Seek(0, SeekOrigin.Begin);
		}
		public void Dispose() {
			this.mutex.Set();
		}
	}
	public static class DataFilesHelper {
		static object dataFilesLock = new object();
		static Dictionary<string, ReusableStream> dataFiles = new Dictionary<string, ReusableStream>();
		public static string DataDirectory {
			get {
#if REALTORWORLDDEMO
				return AppDomain.CurrentDomain.BaseDirectory;
#else
				return EnvironmentHelper.IsClickOnce ? ApplicationDeployment.CurrentDeployment.DataDirectory : GetEntryAssemblyDirectory();
#endif
			}
		}
		public static string DataPath { get { return "Data"; } }
		public static string FindFile(string fileName, string directoryName) {
			string appPath = DataDirectory;
			if(appPath == null) return null;
			string dirName = Path.GetFullPath(appPath);
			for(int n = 0; n < 9; n++) {
				string path = dirName + "\\" + directoryName + "\\" + fileName;
				try {
					if(File.Exists(path) || Directory.Exists(path))
						return path;
				} catch { }
				dirName += @"\..";
			}
			throw new FileNotFoundException(fileName + " not found");
		}
		public static string FindDirectory(string directoryName) {
			string appPath = DataDirectory;
			if(appPath == null) return null;
			string dirName = Path.GetFullPath(appPath);
			for(int n = 0; n < 9; n++) {
				string path = dirName + "\\" + directoryName;
				try {
					if(Directory.Exists(path))
						return path;
				} catch { }
				dirName += @"\..";
			}
			throw new DirectoryNotFoundException(directoryName + " not found");
		}
		public static ReusableStream GetDataFile(string name) {
			ReusableStream stream;
			bool loadData = false;
			lock(dataFilesLock) {
				if(!dataFiles.TryGetValue(name, out stream)) {
					stream = new ReusableStream();
					loadData = true;
					dataFiles.Add(name, stream);
				}
			}
			stream.Reset();
			if(loadData) {
				stream.Data = GetDataFileCore(name);
			}
			return stream;
		}
#if !REALTORWORLDDEMO
		public static void UnpackData(params string[] archiveNames) {
			if(!EnvironmentHelper.IsClickOnce) return;
			string archivesDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
			string dataDirectory = Path.Combine(ApplicationDeployment.CurrentDeployment.DataDirectory, "Data");
			string keyPath = Path.Combine(archivesDirectory, "Key");
			FileStream keyStream = null;
			int i = 60;
			for(; --i >= 0; ) {
				try {
					keyStream = new FileStream(keyPath, FileMode.CreateNew, FileAccess.Write, FileShare.None);
					break;
				} catch {
					try {
						File.Delete(keyPath);
					} catch {
						Thread.Sleep(1000);
					}
				}
			}
			if(i < 0) {
				MessageBox.Show("Unpack data error", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
				return;
			}
			try {
				foreach(string archiveName in archiveNames) {
					string archivePath = Path.Combine(archivesDirectory, archiveName);
					if(!File.Exists(archivePath)) continue;
					using(FileStream archiveStream = new FileStream(archivePath, FileMode.Open, FileAccess.Read)) {
						ZipFileCollection archiveFiles = ZipArchive.Open(archiveStream);
						foreach(ZipFile archiveFile in archiveFiles) {
							string dataFilePath = Path.Combine(dataDirectory, archiveFile.FileName);
							string dataFileDirectory = Path.GetDirectoryName(dataFilePath);
							Directory.CreateDirectory(dataFileDirectory);
							byte[] data = new byte[archiveFile.UncompressedSize];
							archiveFile.FileDataStream.Read(data, 0, data.Length);
							try {
								File.WriteAllBytes(dataFilePath, data);
							} catch { }
						}
					}
				}
			} finally {
				try {
					keyStream.Close();
					File.Delete(keyPath);
				} catch { }
			}
		}
#endif
		static Stream GetDataFileCore(string name) {
			string filePath = FindFile(name, DataPath);
			FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
			return fileStream;
		}
		static string GetEntryAssemblyDirectory() {
			Assembly curr = Assembly.GetEntryAssembly();
			if(curr == null) return null;
			string appPath = curr.Location;
			return Path.GetDirectoryName(appPath);
		}
	}
}
